// -*- coding: utf-8 -*- 
/**
 * Project: PICProcess
 *
 * @author: yanking
 * Create time: 2022-04-20 23:22
 * IDE: IntelliJ IDEA
 * Introduction:
 */
package HistogramEqualization;

import java.awt.image.BufferedImage;

public class TransF {
    double[] count = new double[256];//用来枚举原图各个灰度值个数，灰度级为8
    double[] Count = new double[256];//统计新图的灰度值
    double[] NSK = new double[256];//变换函数

    public BufferedImage run(BufferedImage image) {
        double H, S, I;
        int width = image.getWidth();
        int height = image.getHeight();
        BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int j = 0; j < height; j++) {
            for (int i = 0; i < width; i++) {
                // data是其中的图片的像素数据，是一个一维数组
                Object data = image.getRaster().getDataElements(i, j, null);
                int red = image.getColorModel().getRed(data);
                int blue = image.getColorModel().getBlue(data);
                int green = image.getColorModel().getGreen(data);
                I = ((double) (red + green + blue) / (double) 3);
                if (count[(int) I] == 0) {
                    count[(int) I] = 1;
                } else {
                    count[(int) I] += 1;
                }
            }
        }
        double[] Pr = new double[256];//计算各灰度值出现概率
        for (int i = 0; i < 256; i++) {
            // 当前枚举的数量除以总数量
            Pr[i] = (double) count[i] / (double) (width * height);
        }
        double[] sk = new double[256];//概率累计
        for (int i = 0; i < 256; i++) {
            for (int j = 0; j <= i; j++) {
                sk[i] += Pr[j];
            }
        }

        for (int i = 0; i < 256; i++) {
            NSK[i] = (255 * sk[i] + 0.5);
        }
        int[] rgb = new int[3];
        for (int j = 0; j < height; j++) {
            for (int i = 0; i < width; i++) {
                Object data = image.getRaster().getDataElements(i, j, null);//获取图像个点的rgb值
                int red = image.getColorModel().getRed(data);
                int blue = image.getColorModel().getBlue(data);
                int green = image.getColorModel().getGreen(data);
                int Alpha = image.getColorModel().getAlpha(data);
                //套公式计算H
                double a = (red - green + red - blue)
                        / (2.0 * Math.sqrt((red - green) * (red - green) + (red - blue) * (green - blue)));
                if (green > blue) {
                    H = Math.acos(a);
                } else {
                    H = 2.0 * Math.PI - Math.acos(a);
                }
                I = ((double) (red + green + blue) / (double) 3);
                I = NSK[(int) I];//I经过转化之后的I

                if (Count[(int) I] == 0) {
                    Count[(int) I] = 1;
                } else {
                    Count[(int) I] += 1;
                }
                if (red == green && green == blue) {//若图像为黑白图像的处理
                    rgb[0] = (int) I;
                    rgb[1] = (int) I;
                    rgb[2] = (int) I;
                } else {     //若图像为彩色图像的处理
                    S = 1 - ((double) 3 / (double) (red + green + blue)) * (double) red;//计算S
                    if (H <= 2.09) {
                        rgb[0] = (int) (I * (1.0 + (S * Math.cos(H)) / Math.cos((Math.PI / 3.0) - H)));
                        rgb[0] = Math.min(rgb[0], 255);
                        rgb[0] = Math.max(rgb[0], 0);
                        rgb[2] = (int) (I * (1.0 - S));
                        rgb[2] = Math.max(rgb[2], 0);
                        rgb[2] = Math.min(rgb[2], 255);
                        rgb[1] = (int) (3.0 * I - rgb[0] - rgb[2]);
                        rgb[1] = Math.min(rgb[1], 255);
                        rgb[1] = Math.max(rgb[1], 0);
                    } else if (H > 2.09 && H <= 4.18) {
                        rgb[1] = (int) (I * (1.0 + (S * Math.cos(H - (Math.PI * 2.0 / 3.0))) / Math.cos((Math.PI) - H)));
                        rgb[1] = Math.min(rgb[1], 255);
                        rgb[1] = Math.max(rgb[1], 0);
                        rgb[0] = (int) (I * (1.0 - S));
                        rgb[0] = Math.min(rgb[0], 255);
                        rgb[0] = Math.max(rgb[0], 0);
                        rgb[2] = (int) (3.0 * I - rgb[0] - rgb[1]);
                        rgb[2] = Math.min(rgb[2], 255);
                        rgb[2] = Math.max(rgb[2], 0);
                    } else if (H > 4.18) {
                        rgb[2] = (int) (I * (1.0 + (S * Math.cos(H - (Math.PI * 4.0 / 3.0))) / Math.cos((Math.PI * 5.0 / 3.0) - H)));
                        rgb[2] = Math.min(rgb[2], 255);
                        rgb[2] = Math.max(rgb[2], 0);
                        rgb[1] = (int) (I * (1.0 - S));
                        rgb[1] = Math.min(rgb[1], 255);
                        rgb[1] = Math.max(rgb[1], 0);
                        rgb[0] = (int) (3.0 * I - rgb[1] - rgb[2]);
                        rgb[0] = Math.min(rgb[0], 255);
                        rgb[0] = Math.max(rgb[0], 0);
                    }
                }
                int srgb = Alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0];
                result.setRGB(i, j, srgb);
            }
        }
        return result;
    }
}

